const DownloadTask = require('./DownloadTask');
const ProgressMonitor = require('./ProgressMonitor');
const { ensureDirectory } = require('./utils');
const TaskLogger = require('./TaskLogger');

/**
 * 下载管理器类
 * @class DownloadManager
 */
class DownloadManager {
    /**
     * 构造函数
     * @param {Object} options - 配置选项
     * @param {number} [options.maxConcurrent=3] - 最大并发下载数
     * @param {number} [options.globalSpeedLimit=0] - 全局限速(字节/秒)
     * @param {string} [options.defaultDownloadPath='./downloads'] - 默认下载目录
     * @param {string} [options.logDir='./download-logs'] - 日志目录
     * @param {boolean} [options.restoreTasks=true] - 是否恢复未完成任务
     */
    constructor(options = {}) {
        this.options = {
            maxConcurrent: options.maxConcurrent || 3,
            globalSpeedLimit: options.globalSpeedLimit || 0,
            defaultDownloadPath: options.defaultDownloadPath || './downloads',
            logDir: options.logDir || './download-logs',
            restoreTasks: options.restoreTasks !== false, // 默认true
            ...options
        };

        // 确保默认下载目录存在
        ensureDirectory(this.options.defaultDownloadPath);

        // 初始化日志记录器
        this.logger = new TaskLogger(this.options.logDir);

        // 任务队列
        this.queue = []; // 等待队列
        this.activeDownloads = new Map(); // 进行中的下载
        this.completedDownloads = []; // 已完成的下载

        // 进度监控
        this.monitor = new ProgressMonitor(this);

        // 恢复未完成任务
        if (this.options.restoreTasks) {
            this.restoreUnfinishedTasks();
        }
    }

    /**
     * 恢复未完成的任务
     */
    restoreUnfinishedTasks() {
        const savedStates = this.logger.getAllTaskStates();

        Object.entries(savedStates).forEach(([taskId, state]) => {
            // 只恢复未完成的任务
            if (state.status !== 'completed' && state.status !== 'failed' && state.status !== 'stopped') {
                const downloadTask = new DownloadTask(state.url, state.outputPath, state.options);
                downloadTask.restoreFromState(state);

                this.queue.push({ taskId, downloadTask });
                this.monitor.addTask(taskId, downloadTask);

                this.logger.logEvent('Task restored', { taskId, status: state.status });
            }
        });

        this.logger.logEvent('Manager initialized', {
            restoredTasks: Object.keys(savedStates).length,
            activeTasks: this.queue.length
        });
    }

    /**
     * 添加下载任务
     * @param {string|Object} task - 下载任务URL或配置对象
     * @param {string} [task.url] - 下载URL
     * @param {string} [task.outputPath] - 输出路径
     * @param {Object} [task.options] - 下载选项
     * @return {string} 任务ID
     */
    addTask(task) {
        let url, outputPath, taskOptions = {};

        if (typeof task === 'string') {
            url = task;
            outputPath = path.join(this.options.defaultDownloadPath, path.basename(url));
        } else {
            url = task.url;
            outputPath = task.outputPath || path.join(this.options.defaultDownloadPath, path.basename(task.url));
            taskOptions = task.options || {};
        }

        // 应用全局限速
        if (this.options.globalSpeedLimit > 0 && !taskOptions.speedLimit) {
            taskOptions.speedLimit = this.options.globalSpeedLimit / this.options.maxConcurrent;
        }

        const taskId = this.generateTaskId(url);
        const downloadTask = new DownloadTask(url, outputPath, {
            ...taskOptions,
            onFinish: (result) => {
                this.onTaskFinish(taskId, result);
                taskOptions.onFinish?.(result);
            },
            onError: (error) => {
                this.onTaskError(taskId, error);
                taskOptions.onError?.(error);
            },
            onProgress: (progress) => {
                taskOptions.onProgress?.(progress);
            }
        });

        this.queue.push({ taskId, downloadTask });
        this.monitor.addTask(taskId, downloadTask);

        // 检查是否可以开始下载
        this.checkQueue();

        // 记录新任务
        this.logger.logTaskState(taskId, downloadTask.getStateSnapshot());
        this.logger.logEvent('Task added', { taskId, url });

        return taskId;
    }

    /**
     * 批量添加下载任务
     * @param {Array<string|Object>} tasks - 任务数组
     * @return {Array<string>} 任务ID数组
     */
    addTasks(tasks) {
        return tasks.map(task => this.addTask(task));
    }

    /**
     * 暂停任务
     * @param {string} taskId - 任务ID
     */
    pauseTask(taskId) {
        const task = this.activeDownloads.get(taskId) || this.queue.find(t => t.taskId === taskId)?.downloadTask;
        if (task) {
            task.pause();
            this.logger.logTaskState(taskId, task.getStateSnapshot());
            this.logger.logEvent('Task paused', { taskId });
        }
    }

    /**
     * 恢复任务
     * @param {string} taskId - 任务ID
     */
    resumeTask(taskId) {
        const task = this.activeDownloads.get(taskId) || this.queue.find(t => t.taskId === taskId)?.downloadTask;
        if (task) {
            task.resume();
        }
    }

    /**
     * 停止任务
     * @param {string} taskId - 任务ID
     */
    stopTask(taskId) {
        const task = this.activeDownloads.get(taskId) || this.queue.find(t => t.taskId === taskId)?.downloadTask;
        if (task) {
            task.stop();
            this.logger.logEvent('Task stopped', { taskId });
            this.removeTask(taskId);
        }
    }

    /**
     * 从队列中移除任务
     * @param {string} taskId - 任务ID
     */
    removeTask(taskId) {
        // 从活动下载中移除
        if (this.activeDownloads.has(taskId)) {
            this.activeDownloads.delete(taskId);
        }

        // 从队列中移除
        this.queue = this.queue.filter(t => t.taskId !== taskId);

        // 从监控中移除
        this.monitor.removeTask(taskId);

        // 检查队列是否有新任务可以开始
        this.checkQueue();
    }

    /**
     * 开始所有任务
     */
    startAll() {
        this.queue.forEach(item => {
            if (item.downloadTask.status === 'paused') {
                item.downloadTask.resume();
            }
        });

        this.checkQueue();
    }

    /**
     * 暂停所有任务
     */
    pauseAll() {
        this.activeDownloads.forEach(task => task.pause());
    }

    /**
     * 停止所有任务
     */
    stopAll() {
        this.activeDownloads.forEach(task => task.stop());
        this.activeDownloads.clear();
        this.queue = [];
        this.monitor.stop();
    }

    /**
     * 检查队列并开始新任务
     */
    checkQueue() {
        while (this.activeDownloads.size < this.options.maxConcurrent && this.queue.length > 0) {
            const nextTask = this.queue.shift();

            if (nextTask.downloadTask.status === 'pending' || nextTask.downloadTask.status === 'paused') {
                this.activeDownloads.set(nextTask.taskId, nextTask.downloadTask);
                nextTask.downloadTask.start();
            }
        }

        // 如果没有活动下载且队列为空，停止监控
        if (this.activeDownloads.size === 0 && this.queue.length === 0) {
            this.monitor.stop();
        } else if (!this.monitor.interval) {
            this.monitor.start();
        }
    }

    /**
     * 任务完成回调
     * @param {string} taskId - 任务ID
     * @param {Object} result - 结果对象
     */
    onTaskFinish(taskId, result) {
        const task = this.activeDownloads.get(taskId);
        if (task) {
            this.logger.logTaskState(taskId, task.getStateSnapshot());
            this.logger.logEvent('Task completed', { taskId, ...result });
        }

        this.activeDownloads.delete(taskId);
        this.completedDownloads.push({ taskId, result });
        this.monitor.removeTask(taskId);
        this.logger.removeTaskState(taskId);
        this.checkQueue();
    }

    /**
     * 任务错误回调
     * @param {string} taskId - 任务ID
     * @param {Error} error - 错误对象
     */
    onTaskError(taskId, error) {
        const task = this.activeDownloads.get(taskId);
        if (task) {
            this.logger.logTaskState(taskId, task.getStateSnapshot());
            this.logger.logEvent('Task failed', { taskId, error: error.message });
        }

        this.activeDownloads.delete(taskId);
        this.monitor.removeTask(taskId);
        this.checkQueue();
    }

    /**
     * 生成任务ID
     * @param {string} url - 下载URL
     * @return {string} 任务ID
     */
    generateTaskId(url) {
        return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}-${Buffer.from(url).toString('base64').substring(0, 8)}`;
    }

    /**
     * 设置全局限速
     * @param {number} speedLimit - 速度限制(字节/秒)
     */
    setGlobalSpeedLimit(speedLimit) {
        this.options.globalSpeedLimit = speedLimit;

        // 更新活动任务的限速
        const limitPerTask = speedLimit / this.options.maxConcurrent;
        this.activeDownloads.forEach(task => {
            task.options.speedLimit = limitPerTask;
        });
    }
}

module.exports = DownloadManager;